package com.sojson.project.monitor.job.service.impl;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sojson.project.monitor.job.dao.JobDao;
import com.sojson.project.monitor.job.entity.dto.JobDto;
import com.sojson.project.monitor.job.entity.dto.JobPageDto;
import com.sojson.project.monitor.job.entity.po.Job;
import com.sojson.project.monitor.job.entity.vo.JobVo;
import com.sojson.project.monitor.job.service.JobService;
import com.sojson.util.job.ScheduleConstant;
import com.sojson.util.job.ScheduleUtil;

/**
 * 定时任务调度表Service实现类
 * 
 * @author liu
 * @date 2022-10-24
 */
@Service
public class JobServiceImpl extends ServiceImpl<JobDao, Job> implements JobService {

    @Lazy
    @Autowired
    private JobService jobService;
    @Autowired
    private Scheduler scheduler;
    @Resource
    private JobDao jobDao;

    /**
     * 项目启动时，初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理（注：不能手动修改数据库ID和任务组名，否则会导致脏数据）
     */
    @PostConstruct
    public void init() throws Exception {
        scheduler.clear();

        List<JobVo> jobList = jobDao.list(new JobDto());
        for (JobVo job : jobList) {
            ScheduleUtil.createScheduleJob(scheduler, job);
        }
    }

    /**
     * 单条插入
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(Job dto) throws Exception {
        int insert = jobDao.insert(dto);

        if (insert > 0) {
            ScheduleUtil.createScheduleJob(scheduler, jobDao.findById(dto.getId()));
        }
        return true;
    }

    /**
     * 通过id更新
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(Job dto) throws Exception {
        int rows = jobDao.updateById(dto);

        JobVo properties = jobService.findById(dto.getId());
        if (rows > 0) {
            jobService.updateSchedulerJob(properties, properties.getGroup());
        }
        return true;
    }

    /**
     * 更新任务
     *
     * @param dto      任务对象
     * @param jobGroup 任务组名
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSchedulerJob(JobVo dto, String jobGroup) throws Exception {
        String id = dto.getId();

        // 判断是否存在
        JobKey jobKey = ScheduleUtil.getJobKey(id, jobGroup);

        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        ScheduleUtil.createScheduleJob(scheduler, dto);
    }

    /**
     * 通过对象查找
     * 
     * @param dto
     * @return
     */
    @Override
    public List<JobVo> list(JobDto dto) {
        List<JobVo> list = jobDao.list(dto);
        return list;
    }

    /**
     * 通过对象分页查找
     * 
     * @param dto
     * @return
     */
    @Override
    public List<JobVo> page(JobPageDto dto) {
        List<JobVo> page = jobDao.page(dto);
        return page;
    }

    /**
     * 通过id修改状态
     * 
     * @param ids
     * @return
     * @throws Exception 
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(List<String> ids) throws Exception {
        for (String id : ids) {
            JobVo findById = jobDao.findById(id);
            jobService.deleteJob(findById);
        }
        return true;
    }

    /**
     * 删除任务后,所对应的trigger也将被删除
     * 
     * @param dto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteJob(JobVo job) throws Exception {
        String id = job.getId();
        String group = job.getGroup();

        int rows = jobDao.deleteById(id);
        if (rows > 0) {
            scheduler.deleteJob(ScheduleUtil.getJobKey(id, group));
        }
        return rows;
    }

    /**
     * 通过对象删除
     * 
     * @param dto
     * @return
     */
    @Override
    public boolean removeByDto(JobDto dto) {
        jobDao.removeByDto(dto);
        return true;
    }

    /**
     * 清空数据
     * 
     * @return
     */
    @Override
    public boolean clear() {
        jobDao.clear();
        return true;
    }

    /**
     * 通过id查找
     * 
     * @param id
     * @return
     */
    @Override
    public JobVo findById(String id) {
        JobVo findById = jobDao.findById(id);
        return findById;
    }

    /**
     * 暂停任务
     * 
     * @param dto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int pauseJob(Job dto) throws Exception {
        String id = dto.getId();
        String group = dto.getGroup();
        dto.setStatus(ScheduleConstant.Status.PAUSE.getValue());

        int rows = jobDao.updateById(dto);
        if (rows > 0) {
            scheduler.pauseJob(ScheduleUtil.getJobKey(id, group));
        }
        return rows;
    }

    /**
     * 恢复任务
     * 
     * @param dto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int resumeJob(Job dto) throws Exception {
        String id = dto.getId();
        String group = dto.getGroup();
        dto.setStatus(ScheduleConstant.Status.NORMAL.getValue());

        int rows = jobDao.updateById(dto);
        if (rows > 0) {
            scheduler.resumeJob(ScheduleUtil.getJobKey(id, group));
        }
        return rows;
    }

    /**
     * 通过id修改状态
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @Override
    public int updateStatusById(Job dto) throws Exception {
        int rows = 0;
        Integer status = dto.getStatus();
        if (ScheduleConstant.Status.NORMAL.getValue() == status) {
            rows = resumeJob(dto);
        } else if (ScheduleConstant.Status.PAUSE.getValue() == status) {
            rows = pauseJob(dto);
        }
        return rows;
    }

    /**
     * 定时任务立即执行一次
     * 
     * @param dto
     * @return
     * @throws Exception
     */
    @Override
    public int run(Job dto) throws Exception {
        String id = dto.getId();
        String group = dto.getGroup();
        JobVo properties = findById(id);

        // 参数
        JobDataMap dataMap = new JobDataMap();
        dataMap.put(ScheduleConstant.TASK_PROPERTIES, properties);
        scheduler.triggerJob(ScheduleUtil.getJobKey(id, group), dataMap);

        return 1;
    }

}